<!doctype html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport"
        content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>debounce & throttle</title>

  <script>
    /**
     * 防抖
     * @param func 执行函数
     * @param delay 延迟毫秒
     * @param immediate 是否第一次调用立即执行
     */
    const debounce = (func, delay, immediate = false) => {
      let timer
      return function (...args) {
        clearTimeout(timer)

        if (immediate) {
          const callNow = !timer
          timer = setTimeout(() => {
            func.apply(this, args) // 确保最后一次执行
            timer = null
          }, delay)
          if (callNow) {
            func.apply(this, args)
            clearTimeout(timer) // 防止重复执行
          }
        } else {
          timer = setTimeout(() => {
            func.apply(this, args)
          }, delay)
        }

      }
    }
    const debounceSimple = (func, delay) => {
      let timer

      return function (...args) {
        clearTimeout(timer)
        timer = setTimeout(() => {
          func.apply(this, args)
        }, delay)
      }
    }


    const mDebounce = debounce((fn) => fn(), 1000, true)

    const testDebounce = () => {
      console.log('.')
      mDebounce(() => {
        console.log('exec:debounce')
      })
    }

    /**
     * 节流函数
     * @param func 执行函数
     * @param delay 延迟毫秒
     * @param isLastExec 是否在最后一次执行
     */
    let finTimer
    const throttle = function (func, delay, isLastExec) {
      let prev = Date.now()

      return function (...args) {
        const now = Date.now()
        clearTimeout(finTimer)

        if (now - prev >= delay) {
          func.apply(this, args)
          prev = Date.now()
        } else if (isLastExec) {
          finTimer = setTimeout(() => {
            func.apply(this, args)
          }, delay)
        }
      }
    }

    const mThrottle = throttle((fn) => fn(), 1000, true)

    const testThrottle = () => {
      console.log('*')
      mThrottle(() => {
        console.log('exec:throttle')
      })
    }
  </script>
</head>
<body>
<p>Open console, watch output. Fast clicking a single button to see the function effect.</p>
<button onclick="testDebounce()">debounce</button>
<button onclick="testThrottle()">throttle</button>
</body>
</html>
